package com.ia.aistream.manager.framework.redis;


import org.springframework.data.redis.core.ZSetOperations;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 字符串常用命令封装开始
 *
 * @author chenjunsheng
 */
public interface RedisManager {
    /**
     * 检查给定 key 是否存在。
     *
     * @param key
     * @return 若 key 存在，返回 true ，否则返回 false 。
     */
    Boolean exists(String key);

    /**
     * 删除redis中key值（key值内容不限）
     *
     * @param key
     */
    void del(String key, String... keys);

    /**
     * 查找所有符合给定模式 pattern 的 key ， 比如说：
     * <p>
     * KEYS * 匹配数据库中所有 key 。
     * KEYS h?llo 匹配 hello ， hallo 和 hxllo 等。
     * KEYS h*llo 匹配 hllo 和 heeeeello 等。
     * KEYS h[ae]llo 匹配 hello 和 hallo ，但不匹配 hillo 。
     *
     * @param pattern
     * @return
     */
    Set<String> keys(String pattern);

    /**
     * 设置自动过期
     *
     * @param key     key
     * @param timeout 秒
     */
    void expire(String key, long timeout);

    /**
     * 设置自动过期
     *
     * @param key     key
     * @param timeout 秒
     * @param unit    时间单位
     */
    void expire(String key, long timeout, TimeUnit unit);

    /**
     * 标记一个事务块的开始。
     */
    void multi();

    /**
     * 执行所有事务块内的命令。
     */
    void exec();

    /**
     * 取消事务，放弃执行事务块内的所有命令。
     */
    void discard();

    /**
     * 分布式锁
     *
     * @param key
     * @param timeout
     * @return
     */
    String lock(String key, int timeout);

    /**
     * 释放分布式锁
     *
     * @param key
     * @param lock
     */
    void unlock(String key, String lock);


    // ======================================================string======================================================

    /**
     * SET 命令。
     *
     * @param key   键
     * @param value 值
     */
    void set(String key, Object value);

    /**
     * <b>SETNX:</b>
     * 只在键 key 不存在的情况下， 将键 key 的值设置为 value 。
     * <p>
     * 若键 key 已经存在， 则 SETNX 命令不做任何动作。
     * <p>
     * SETNX 是『SET if Not eXists』(如果不存在，则 SET)的简写。
     *
     * @param key
     * @param value
     * @return
     */
    Boolean setnx(String key, Object value);

    /**
     * 参考 SETEX 命令。
     *
     * @param key     键
     * @param seconds 失效时间，单位：秒
     * @param value   键
     */
    void setex(String key, int seconds, Object value);

    /**
     * 这个命令和 SETEX 命令相似， 但它以毫秒为单位设置 key 的生存时间， 而不是像 SETEX 命令那样以秒为单位进行设置。
     *
     * @param key
     * @param milliseconds
     * @param value
     */
    void psetex(String key, long milliseconds, Object value);


    /**
     * 参考 GET 命令。
     *
     * @param key   键
     * @param clazz 强转类型
     * @return 如果键 key 不存在，那么返回特殊值 nil；否则，返回键 key 的值。如果键 key 的值并非字符串类型，那么返回一个错误，因为 GET 命令只能用于字符串值。
     */
    <T> T get(String key, Class<T> clazz);

    /**
     * GETSET key value
     * 将键 key 的值设为 value ， 并返回键 key 在被设置之前的旧值。
     *
     * @param key
     * @param value
     * @return
     */
    <T> T getSet(String key, T value);

    /**
     * STRLEN 命令返回字符串值的长度。
     * <p>
     * 当键 key 不存在时， 命令返回 0 。
     * <p>
     * 当 key 储存的不是字符串值时， 返回一个错误。
     *
     * @param key
     * @return
     */
    Long strLen(String key);

    /**
     * 为键 key 储存的数字值加上一。
     *
     * @param key
     * @return
     */
    Long incr(String key);

    /**
     * INCRBY key increment
     * <p>
     * 为键 key 储存的数字值加上增量 increment 。
     *
     * @param key
     * @param increment
     */
    void incrby(String key, long increment);

    /**
     * 为键 key 储存的值加上浮点数增量 increment 。
     *
     * @param key
     * @param increment
     */
    void incrbyfloat(String key, double increment);


    /**
     * 参考 MGET 命令。
     *
     * @param keys  键列表
     * @param clazz
     * @return 值列表，列表中包含了所有给定键的值。
     */
    <T> List<T> mget(Collection<String> keys, Class<T> clazz);


    // ======================================================hash======================================================

    /**
     * 参考 HSET 命令
     *
     * @param key
     * @param field
     * @param value
     */
    void hset(String key, String field, Object value);

    /**
     * 当且仅当域 field 尚未存在于哈希表的情况下， 将它的值设置为 value 。
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    boolean hsetnx(String key, String field, Object value);

    /**
     * 返回哈希表中给定域的值。
     *
     * @param key
     * @param field
     * @param clazz
     * @return
     */
    <V> V hget(String key, String field, Class<V> clazz);

    /**
     * 检查给定域 field 是否存在于哈希表 hash 当中。
     *
     * @param key
     * @param field
     * @return
     */
    boolean hexists(String key, String field);

    /**
     * 删除哈希表 key 中的一个或多个指定域，不存在的域将被忽略。
     *
     * @param key
     * @param fields
     */
    void hdel(String key, Object... fields);

    /**
     * 返回哈希表 key 中域的数量。
     *
     * @param key
     * @return
     */
    Long hlen(String key);

    /**
     * 返回哈希表 key 中， 与给定域 field 相关联的值的字符串长度（string length）。
     *
     * @param key
     * @param field
     * @return
     */
    Long hstrlen(String key, String field);

    /**
     * 为哈希表 key 中的域 field 的值加上增量 increment 。
     *
     * @param key
     * @param field
     * @param increment
     * @return
     */
    Long hincrby(String key, String field, long increment);

    /**
     * 为哈希表 key 中的域 field 的值加上增量 increment 。
     *
     * @param key
     * @param field
     * @param increment
     * @return
     */
    Double hincrbyfloat(String key, String field, double increment);

    /**
     * 设置多个值
     *
     * @param key
     * @param map
     */
    <V> void hmset(String key, Map<String, V> map);

    /**
     * 获取多个值
     *
     * @param key
     * @param fields
     * @param clazz
     * @return
     */
    <V> List<V> hmget(String key, Collection<String> fields, Class<V> clazz);

    /**
     * 返回哈希表 key 中的所有域。
     *
     * @param key
     * @return
     */
    Set<String> hkeys(String key);

    /**
     * 返回哈希表 key 中所有域的值。
     *
     * @param key
     * @param clazz
     * @return
     */
    <V> List<V> hvals(String key, Class<V> clazz);

    /**
     * 参考 HGETALL 命令
     *
     * @param key   哈希表名称
     * @param clazz
     * @return 哈希表 key 中，所有的域和值
     */
    <V> Map<String, V> hgetall(String key, Class<V> clazz);

    // ======================================================list======================================================

    // ======================================================set======================================================

    /**
     * 将一个或多个 member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略。
     *
     * @param key     假如 key 不存在，则创建一个只包含 member 元素作成员的集合。当 key 不是集合类型时，返回一个错误。
     * @param members 被添加到集合中的新元素
     */
    void sadd(String key, Object... members);

    /**
     * 判断 member 元素是否集合 key 的成员。
     *
     * @param key    key
     * @param member 集合的成员
     * @return
     */
    boolean sismembers(String key, Object member);

    /**
     * 返回集合 key 中的所有成员。
     *
     * @param <T>   枚举
     * @param key   key
     * @param clazz
     * @return
     */
    <T> Set<T> smembers(String key, Class<T> clazz);

    /**
     * 移除集合 key 中的一个或多个 member 元素，不存在的 member 元素会被忽略。
     *
     * @param key    key
     * @param member 元素
     */
    void srem(String key, Object member);

    /**
     * 将 member 元素从 source 集合移动到 destination 集合。
     *
     * @param source      来源集合
     * @param destination 目标集合
     * @param member      元素
     */
    void smove(String source, String destination, Object member);

    /**
     * 返回集合 key 的基数(集合中元素的数量)。
     *
     * @param key key
     * @return 集合的基数。 当 key 不存在时，返回 0 。
     */
    long scard(String key);

    // ======================================================zset======================================================

    /**
     * 将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
     *
     * @param key
     * @param score
     * @param member
     */
    void zadd(String key, double score, Object member);

    /**
     * 返回有序集 key 中，成员 member 的 score 值。
     *
     * @param key
     * @param member
     * @return
     */
    Double zscore(String key, Object member);

    /**
     * 为有序集 key 的成员 member 的 score 值加上增量 increment 。
     *
     * @param key
     * @param increment
     * @param member
     * @return member 成员的新 score 值，以字符串形式表示。
     */
    Double zincrby(String key, double increment, Object member);

    /**
     * 返回有序集 key 的基数。
     *
     * @param key
     * @return 当 key 存在且是有序集类型时，返回有序集的基数。 当 key 不存在时，返回 0 。
     */
    long zcard(String key);

    /**
     * 返回有序集 key 中，指定区间内的成员。其中成员的位置按 score 值递增(从小到大)来排序。具有相同 score 值的成员按字典序(lexicographical order )来排列。
     *
     * @param <T>
     * @param key
     * @param start
     * @param stop
     * @param clazz
     * @return 指定区间内，带有 score 值(可选)的有序集成员的列表。
     */
    <T> Set<T> zrange(String key, int start, int stop, Class<T> clazz);

    /**
     * 返回有序集 key 中，指定区间内的成员。其中成员的位置按 score 值递增(从小到大)来排序。具有相同 score 值的成员按字典序(lexicographical order )来排列。
     *
     * @param <T>
     * @param key
     * @param start
     * @param stop
     * @param withscores
     * @param clazz
     * @return 指定区间内，带有 score 值(可选)的有序集成员的列表。
     */
    <T> Set<ZSetOperations.TypedTuple<T>> zrange(String key, int start, int stop, boolean withscores, Class<T> clazz);

    /**
     * 返回有序集 key 中，所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
     *
     * @param <T>
     * @param key
     * @param min
     * @param max
     * @param clazz
     * @return
     */
    <T> Set<T> zrangebyscore(String key, double min, double max, Class<T> clazz);

    /**
     * 返回有序集 key 中，所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
     *
     * @param <T>
     * @param key
     * @param min
     * @param max
     * @param offset
     * @param count
     * @param clazz
     * @return
     */
    <T> Set<T> zrangebyscore(String key, double min, double max, int offset, int count, Class<T> clazz);

    /**
     * 返回有序集 key 中，所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
     *
     * @param key
     * @param min
     * @param max
     * @param withscores
     * @param offset
     * @param count
     * @param clazz
     * @param <T>
     * @return
     */
    <T> Set<ZSetOperations.TypedTuple<T>> zrangebyscore(String key, double min, double max, boolean withscores, int offset, int count, Class<T> clazz);

    /**
     * 返回有序集 key 中，指定区间内的成员。
     * <p>
     * 其中成员的位置按 score 值递减(从大到小)来排列。 具有相同 score 值的成员按字典序的逆序
     *
     * @param <T>
     * @param key
     * @param start
     * @param stop
     * @param clazz
     * @return 返回有序集 key 中，指定区间内的成员。
     */
    <T> Set<T> zrevrange(String key, int start, int stop, Class<T> clazz);

    /**
     * 移除有序集 key 中的一个或多个成员，不存在的成员将被忽略。
     *
     * @param key
     * @param member
     */
    void zrem(String key, Object member);
}
